//! Sleeping locks
//! Long-term locks for processes
const Sleep = @This();

/// Is the lock held?
locked: bool = false,
/// spinlock protecting this sleep lock
spin: Spin = .init("sleeplock"),

/// Name of lock. For debugging
name: []const u8,
/// Process holding lock
pid: proc.pid_t = 0,

pub fn init(name: []const u8) Sleep {
    return .{ .name = name };
}

pub fn holding(self: *Sleep) bool {
    self.spin.acquire();
    defer self.spin.release();

    const p = proc.current().?;
    return self.locked and self.pid == p.pid;
}

pub fn acquire(self: *Sleep) void {
    self.spin.acquire();
    defer self.spin.release();

    const p = proc.current().?;
    while (self.locked)
        p.sleep(self, &self.spin);

    self.locked = true;
    self.pid = p.pid;
}

pub fn release(self: *Sleep) void {
    self.spin.acquire();
    defer self.spin.release();

    self.locked = false;
    self.pid = 0;
    proc.wakeup(self);
}

const os = @import("../os.zig");
const Spin = @import("Spin.zig");
const proc = os.proc;
